package main

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"sync"
	"sync/atomic"
	"time"

	"github.com/gordonklaus/portaudio"
)

var input *portaudio.Stream

const sampleRate = 44100
const bufferLen = 22050

var in = make([]int16, bufferLen) // 44100是采样率，根据需要调整大小和采样率
var rdLocker = &sync.Mutex{}
var playCtrlStop chan int
var playFlag = &atomic.Bool{}
var mutexPlayer = &sync.Mutex{}

func init() {
	playFlag.Store(false)
	var err error
	err = portaudio.Initialize()
	if err != nil {
		ErrPanic(err)
	}
	input, err = portaudio.OpenDefaultStream(1, 0, sampleRate, len(in), in)
	if err != nil {
		ErrPanic(err)
	}
	input.Start()
	go func() {
		for {
			rdLocker.Lock()
			err := input.Read()
			rdLocker.Unlock()
			if err != nil {
				break
			}
		}

	}()
	playCtrlStop = make(chan int)
}

func startRecord(filename string, ctrl chan int8) error {

	os.MkdirAll("audios", os.ModePerm)
	name := filepath.Join("audios", filename)
	recordFlag.Store(true)
	defer recordFlag.Store(false)

	writer := NewAudioFile()
	err := writer.Create(name)
	if err != nil {
		return err
	}
	defer writer.Close()
	rdLocker.Lock()
	defer rdLocker.Unlock()

loop:
	for {
		err := writer.Write(in)
		if err != nil {
			fmt.Println("保存数据失败:", err)
			return err
		}
		select {
		case <-ctrl:
			ctrl <- 1
			break loop
		default:
		}
		//println("record...")
		err = input.Read() // 读取数据到缓冲区
		if err != nil {
			fmt.Println("读取数据失败:", err)
			return err
		}

	}

	return nil
}

func stopRecord(ctrl chan int8) error {
	ctrl <- 0
	<-ctrl
	return nil
}

func stopPlay() {
	if playFlag.Load() {
		playCtrlStop <- 1
		<-playCtrlStop
		//println("stop ok")
	}

}

func stopPlayForRecord() {
	if playFlag.Load() {
		playCtrlStop <- 1
		<-playCtrlStop

		time.Sleep(time.Millisecond * 500)

		//println("stop ok")
	}

}

func playAudio(filename string) error {

	if playFlag.Load() {

		return errors.New("Playing other audio")

	}

	name := filepath.Join("audios", filename)

	reader := NewAudioFile()
	err := reader.Open(name)
	if err != nil {
		return err
	}
	defer reader.Close()
	mutexPlayer.Lock()
	defer mutexPlayer.Unlock()
	playFlag.Store(true)
	defer playFlag.Store(false)

	//打开pa播放流
	out := make([]int16, bufferLen)

	output, err := portaudio.OpenDefaultStream(0, 1, sampleRate, len(out), out)
	if err != nil {
		fmt.Println("打开输出流失败:", err)
		return err
	}
	defer output.Close() // 关闭输出流

	output.Start()
	defer output.Close()

	n, err := reader.Read(out)
	if err != nil {
		return nil
	}
	for {
		output.Write()
		d := time.Duration(float64(time.Second) * float64(n) / float64(sampleRate))
		after := time.After(d)
		//利用等待时间读取下一段数据，使播放效果更流畅
		n, err = reader.Read(out)
		select {
		case <-playCtrlStop:
			playCtrlStop <- 2
			//println("stop play not complete")
			return nil
		case <-after:
			//println("stop play complete:", d)
		}
		if err != nil {
			return nil
		}
	}
	//pa播放

}
